import { GameObject } from '@/assets/GameObject.js'
import { PlayerParticle } from '@/assets/player/PlayerParticle.js'
import { Fireball } from '@/assets/skills/Fireball.js'
import { Flash } from '@/assets/skills/Flash.js'
import { Heal } from '@/assets/skills/Heal.js'

/**
 * 玩家基类，继承自GameObject基类
 * 负责管理玩家的通用逻辑
 */
export class PlayerBase extends GameObject {
    /**
     * 构造函数，初始化玩家
     * @param {GameMapBase} gameMap - 游戏地图类
     * @param {{}} info - 玩家信息(x, y, radius, color, speed, hp, role, photo, username, userId)
     */
    constructor(gameMap, info) {
        super()
        this.gameMap = gameMap
        this.info = info

        this.width = this.gameMap.ctx.canvas.width
        this.height = this.gameMap.ctx.canvas.height

        // 玩家是否死亡
        this.isDead = false
        // 移动距离
        this.moveLength = 0
        // 速度方向
        this.vx = 0
        this.vy = 0
        // 精度
        this.eps = 0.1
        // 当前所选技能
        this.currentSkill = null
        // 受伤后的速度
        this.damageVx = 0
        this.damageVy = 0
        this.damageSpeed = 0
        // 摩擦力
        this.friction = 0.9
        // 开局保护时间
        this.spentTime = 0
        // 最大血量
        this.maxHp = this.info.hp || 100

        this.initialize_player_avatar()
        this.initialize_skills()
    }

    //为所有玩家加载头像
    initialize_player_avatar() {
        this.avatar = new Image()
        this.hasAvatar = false
        if (this.info.role !== 'AI') {
            try {
                if (this.info.photo && this.info.photo.trim() !== '') {
                    this.avatar.src = this.info.photo
                } else {
                    this.avatar.src = 'https://www.helloimg.com/i/2024/12/22/6767fd5a3cf23.jpg'
                }
            } catch (error) {
                console.error('获取用户头像失败:', error)
                this.avatar.src = 'https://www.helloimg.com/i/2024/12/22/6767fd5a3cf23.jpg'
            }
        }

        this.avatar.onload = () => {
            this.hasAvatar = true
        }
    }

    // 初始化技能
    initialize_skills() {
        this.skills = {
            fireball: new Fireball(this),
            heal: new Heal(this),
            flash: new Flash(this),
        }
    }

    // 计算两点之间的距离
    get_dist(x1, y1, x2, y2) {
        return Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
    }

    // 移动到指定位置
    move_to(tx, ty) {
        this.moveLength = this.get_dist(this.info.x, this.info.y, tx, ty)
        let angle = Math.atan2(ty - this.info.y, tx - this.info.x)
        this.vx = Math.cos(angle)
        this.vy = Math.sin(angle)
    }

    // 玩家受伤产生一些粒子特效
    show_particles() {
        //随机掉落粒子
        for (let i = 0; i < 20 + Math.random() * 5; i++) {
            const info = {
                x: this.info.x,
                y: this.info.y,
                radius: this.info.radius * Math.random() * 0.1,
                vx: Math.cos(Math.PI * 2 * Math.random()),
                vy: Math.sin(Math.PI * 2 * Math.random()),
                color: this.info.color,
                speed: this.info.speed * 10,
                moveLength: this.info.radius * Math.random() * 10,
            }
            new PlayerParticle(this.gameMap, info)
        }
    }

    // 受到攻击
    be_attacked(angle, damage) {
        this.show_particles()

        this.info.hp -= damage
        if (this.info.hp <= 0) {
            this.isDead = true
            this.destroy()
            return false
        }
        this.damageVx = Math.cos(angle)
        this.damageVy = Math.sin(angle)
        this.damageSpeed = damage * this.height * 0.1
    }

    // 更新玩家移动
    update_player_move() {
        if (this.damageSpeed > 10) {
            this.vx = this.vy = 0
            this.moveLength = 0
            this.info.x += (this.damageVx * this.damageSpeed * this.timeDelta) / 1000
            this.info.y += (this.damageVy * this.damageSpeed * this.timeDelta) / 1000
            this.damageSpeed *= this.friction
        } else {
            if (this.moveLength < this.eps) {
                this.vx = this.vy = 0
                this.moveLength = 0
            } else {
                let moved = Math.min(this.moveLength, (this.info.speed * this.timeDelta) / 1000)
                this.info.x += this.vx * moved
                this.info.y += this.vy * moved
                this.moveLength -= moved
            }
        }
    }

    start() {
        // 子类中实现
    }

    update() {
        if (this.isDead) {
            return
        }

        // 增加保护时间计数
        this.spentTime += this.timeDelta / 1000

        this.update_player_move()

        this.draw()
    }

    // 绘制玩家信息
    draw_player_info() {
        // 使用玩家头像渲染
        if (this.hasAvatar) {
            this.gameMap.ctx.save()
            this.gameMap.ctx.beginPath()
            this.gameMap.ctx.arc(this.info.x, this.info.y, this.info.radius, 0, Math.PI * 2)
            this.gameMap.ctx.clip()
            this.gameMap.ctx.drawImage(
                this.avatar,
                this.info.x - this.info.radius,
                this.info.y - this.info.radius,
                this.info.radius * 2,
                this.info.radius * 2,
            )
            this.gameMap.ctx.restore()
            // 使用普通颜色渲染
        } else {
            this.gameMap.ctx.beginPath()
            this.gameMap.ctx.fillStyle = this.info.color
            this.gameMap.ctx.arc(this.info.x, this.info.y, this.info.radius, 0, Math.PI * 2)
            this.gameMap.ctx.fill()
        }
        // 在玩家上方显示用户名
        this.gameMap.ctx.font = `${this.info.radius * 0.4}px Arial`
        this.gameMap.ctx.fillStyle = 'white'
        this.gameMap.ctx.textAlign = 'center'
        this.gameMap.ctx.fillText(
            this.info.username || 'Player',
            this.info.x,
            this.info.y - this.info.radius * 1.5,
        )

        // 在玩家下方显示血量数字
        this.gameMap.ctx.font = `${this.info.radius * 0.3}px Arial`
        this.gameMap.ctx.fillStyle = 'white'
        this.gameMap.ctx.textAlign = 'center'
        this.gameMap.ctx.fillText(
            `HP: ${Math.max(0, Math.floor(this.info.hp))}/${Math.floor(this.maxHp)}`,
            this.info.x,
            this.info.y + this.info.radius * 1.8,
        )

        // 在血量下方显示玩家相对位置
        const relativeX = Math.round((this.info.x / this.width) * 100)
        const relativeY = Math.round((this.info.y / this.height) * 100)
        this.gameMap.ctx.font = `${this.info.radius * 0.8}px Arial`
        this.gameMap.ctx.fillStyle = 'rgba(0, 255, 0, 1)'
        this.gameMap.ctx.textAlign = 'center'
        this.gameMap.ctx.fillText(
            `位置: ${relativeX}%, ${relativeY}%`,
            this.info.x,
            this.info.y + this.info.radius * 2.4,
        )
    }

    // 绘制玩家血条
    draw_player_life_bar() {
        // 计算血量比例
        const hpRatio = Math.max(0, this.info.hp / this.maxHp)

        // 计算血条的宽度和半径
        const healthBarWidth = this.info.radius * 0.2
        const healthBarRadius = this.info.radius + healthBarWidth / 2

        if (hpRatio > 0) {
            this.gameMap.ctx.beginPath()
            // 从顶部开始，顺时针绘制血条，长度根据血量比例计算
            const startAngle = -Math.PI / 2 // 从顶部开始
            const endAngle = startAngle + Math.PI * 2 * hpRatio

            // 创建渐变
            let gradient
            // 健康状态 - 绿色渐变
            if (hpRatio > 0.6) {
                gradient = this.gameMap.ctx.createLinearGradient(
                    this.info.x - healthBarRadius,
                    this.info.y - healthBarRadius,
                    this.info.x + healthBarRadius,
                    this.info.y + healthBarRadius,
                )
                gradient.addColorStop(0, 'rgba(0, 255, 0, 0.7)')
                gradient.addColorStop(0.5, 'rgba(50, 255, 50, 1)')
                gradient.addColorStop(1, 'rgba(0, 200, 0, 0.8)')
                // 警告状态 - 黄色/橙色渐变
            } else if (hpRatio > 0.3) {
                gradient = this.gameMap.ctx.createLinearGradient(
                    this.info.x - healthBarRadius,
                    this.info.y - healthBarRadius,
                    this.info.x + healthBarRadius,
                    this.info.y + healthBarRadius,
                )
                gradient.addColorStop(0, 'rgba(255, 255, 0, 0.7)')
                gradient.addColorStop(0.5, 'rgba(255, 165, 0, 1)')
                gradient.addColorStop(1, 'rgba(255, 140, 0, 0.8)')
                // 危险状态 - 红色渐变
            } else {
                gradient = this.gameMap.ctx.createLinearGradient(
                    this.info.x - healthBarRadius,
                    this.info.y - healthBarRadius,
                    this.info.x + healthBarRadius,
                    this.info.y + healthBarRadius,
                )
                gradient.addColorStop(0, 'rgba(255, 50, 0, 0.7)')
                gradient.addColorStop(0.5, 'rgba(255, 0, 0, 1)')
                gradient.addColorStop(1, 'rgba(200, 0, 0, 0.8)')
            }

            this.gameMap.ctx.arc(this.info.x, this.info.y, healthBarRadius, startAngle, endAngle)
            this.gameMap.ctx.lineCap = 'round'
            this.gameMap.ctx.strokeStyle = gradient
            this.gameMap.ctx.lineWidth = healthBarWidth

            // 添加发光效果
            if (hpRatio < 0.3) {
                // 血量低时闪烁效果
                const pulseIntensity = Math.sin(Date.now() * 0.005) * 0.5 + 0.5
                this.gameMap.ctx.shadowBlur = 10 + 5 * pulseIntensity
                this.gameMap.ctx.shadowColor =
                    'rgba(255, 0, 0, ' + (0.7 + 0.3 * pulseIntensity) + ')'
            } else {
                this.gameMap.ctx.shadowBlur = 10
                this.gameMap.ctx.shadowColor =
                    hpRatio > 0.6 ? 'rgba(0, 255, 0, 0.7)' : 'rgba(255, 165, 0, 0.7)'
            }

            this.gameMap.ctx.stroke()
            this.gameMap.ctx.shadowBlur = 0 // 重置阴影
        }
    }

    // 绘制技能图标（基类默认不显示技能图标）
    draw_skill_icon() {
        // 由子类实现
    }

    draw() {
        if (this.isDead) {
            return
        }

        this.draw_player_info()
        this.draw_player_life_bar()
        this.draw_skill_icon()
    }

    destroy() {
        if (this.gameMap && typeof this.gameMap.remove_player === 'function') {
            this.gameMap.remove_player(this)
        }
    }
}
